<!doctype html>
<html>
<head>
  <title>WebRTC: Simple RTCDataChannel sample</title>
  <!--view-source:https://mdn-samples.mozilla.org/s/webrtc-simple-datachannel/-->
  <meta charset="utf-8">
  <!--view-source:https://mdn-samples.mozilla.org/s/webrtc-simple-datachannel/main.css-->
  <!--<link rel="stylesheet" href="main.css" type="text/css" media="all">-->
  <style>
    body {
      font-family: "Lucida Grande", "Arial", sans-serif;
      font-size: 16px;
    }

    .messagebox {
      border: 1px solid black;
      padding: 5px;
      width: 450px;
    }

    .buttonright {
      float: right;
    }

    .buttonleft {
      float: left;
    }

    .controlbox {
      padding: 5px;
      width: 450px;
      height: 28px;
    }
  </style>
  <!--适配器可以不要-->
  <!--view-source:https://mdn-samples.mozilla.org/s/adapter.js-->
  <!--<script src="../adapter.js"></script>-->
  <!--<script src="https://mdn-samples.mozilla.org/s/adapter.js"></script>-->
  <!--view-source:https://mdn-samples.mozilla.org/s/webrtc-simple-datachannel/main.js-->
  <!--<script src="main.js"></script>-->
  <script>
    // (function () {

      // Define "global" variables

      let connectButton = null;
      let disconnectButton = null;
      let sendButton = null;
      let messageInputBox = null;
      let receiveBox = null;

      let localConnection = null;   // RTCPeerConnection for our "local" connection
      let remoteConnection = null;  // RTCPeerConnection for the "remote"

      let sendChannel = null;       // RTCDataChannel for the local (sender)
      let receiveChannel = null;    // RTCDataChannel for the remote (receiver)

      // Functions

      // Set things up, connect event listeners, etc.

      function startup() {
        connectButton = document.getElementById('connectButton');
        disconnectButton = document.getElementById('disconnectButton');
        sendButton = document.getElementById('sendButton');
        messageInputBox = document.getElementById('message');
        receiveBox = document.getElementById('receivebox');

        // Set event listeners for user interface widgets

        connectButton.addEventListener('click', connectPeers, false);
        disconnectButton.addEventListener('click', disconnectPeers, false);
        sendButton.addEventListener('click', sendMessage, false);
      }

      // Connect the two peers. Normally you look for and connect to a remote
      // machine here, but we're just connecting two local objects, so we can
      // bypass that step.

      function connectPeers() {
        // Create the local connection and its event listeners

        localConnection = new RTCPeerConnection(null);

        // Create the data channel and establish its event listeners
        sendChannel = localConnection.createDataChannel("sendChannel");
        sendChannel.onopen = handleSendChannelStatusChange;
        sendChannel.onclose = handleSendChannelStatusChange;

        // Create the remote connection and its event listeners

        remoteConnection = new RTCPeerConnection(null);
        // ondatachannel似乎需要adapter适配?
        remoteConnection.ondatachannel = receiveChannelCallback;

        // Set up the ICE candidates for the two peers

        localConnection.onicecandidate = e => !e.candidate
          || remoteConnection.addIceCandidate(e.candidate)
            .catch(handleAddCandidateError);

        remoteConnection.onicecandidate = e => !e.candidate
          || localConnection.addIceCandidate(e.candidate)
            .catch(handleAddCandidateError);

        // Now create an offer to connect; this starts the process

        localConnection.createOffer()
          .then(offer => localConnection.setLocalDescription(offer))
          .then(() => remoteConnection.setRemoteDescription(localConnection.localDescription))
          .then(() => remoteConnection.createAnswer())
          .then(answer => remoteConnection.setLocalDescription(answer))
          .then(() => localConnection.setRemoteDescription(remoteConnection.localDescription))
          .catch(handleCreateDescriptionError);
      }

      // Handle errors attempting to create a description;
      // this can happen both when creating an offer and when
      // creating an answer. In this simple example, we handle
      // both the same way.

      function handleCreateDescriptionError(error) {
        console.log("Unable to create an offer: " + error.toString());
      }

      // Handle successful addition of the ICE candidate
      // on the "local" end of the connection.

      function handleLocalAddCandidateSuccess() {
        connectButton.disabled = true;
      }

      // Handle successful addition of the ICE candidate
      // on the "remote" end of the connection.

      function handleRemoteAddCandidateSuccess() {
        disconnectButton.disabled = false;
      }

      // Handle an error that occurs during addition of ICE candidate.

      function handleAddCandidateError() {
        console.log("Oh noes! addICECandidate failed!");
      }

      // Handles clicks on the "Send" button by transmitting
      // a message to the remote peer.

      function sendMessage() {
        let message = messageInputBox.value;
        sendChannel.send(message);

        // Clear the input box and re-focus it, so that we're
        // ready for the next message.

        messageInputBox.value = "";
        messageInputBox.focus();
      }

      // Handle status changes on the local end of the data
      // channel; this is the end doing the sending of data
      // in this example.

      function handleSendChannelStatusChange(event) {
        console.log('handleSendChannelStatusChange', event);
        if (sendChannel) {
          let state = sendChannel.readyState;

          if (state === "open") {
            messageInputBox.disabled = false;
            messageInputBox.focus();
            sendButton.disabled = false;
            handleLocalAddCandidateSuccess();
            disconnectButton.disabled = false;
            handleRemoteAddCandidateSuccess();
            connectButton.disabled = true;
          } else {
            messageInputBox.disabled = true;
            sendButton.disabled = true;
            connectButton.disabled = false;
            disconnectButton.disabled = true;
          }
        }
      }

      // Called when the connection opens and the data
      // channel is ready to be connected to the remote.

      function receiveChannelCallback(event) {
        console.log('receiveChannelCallback', event);
        receiveChannel = event.channel;
        receiveChannel.onmessage = handleReceiveMessage;
        receiveChannel.onopen = handleReceiveChannelStatusChange;
        receiveChannel.onclose = handleReceiveChannelStatusChange;
      }

      // Handle onmessage events for the receiving channel.
      // These are the data messages sent by the sending channel.

      function handleReceiveMessage(event) {
        let el = document.createElement("p");
        let txtNode = document.createTextNode(event.data);

        el.appendChild(txtNode);
        receiveBox.appendChild(el);
      }

      // Handle status changes on the receiver's channel.

      function handleReceiveChannelStatusChange(event) {
        console.log('handleReceiveChannelStatusChange', event);
        if (receiveChannel) {
          console.log("Receive channel's status has changed to " +
            receiveChannel.readyState);
        }

        // Here you would do stuff that needs to be done
        // when the channel's status changes.
      }

      // Close the connection, including data channels if they're open.
      // Also update the UI to reflect the disconnected status.

      function disconnectPeers() {

        // Close the RTCDataChannels if they're open.

        sendChannel.close();
        receiveChannel.close();

        // Close the RTCPeerConnections

        localConnection.close();
        remoteConnection.close();

        sendChannel = null;
        receiveChannel = null;
        localConnection = null;
        remoteConnection = null;

        // Update user interface elements

        connectButton.disabled = false;
        disconnectButton.disabled = true;
        sendButton.disabled = true;

        messageInputBox.value = "";
        messageInputBox.disabled = true;
      }

      // Set up an event listener which will run the startup
      // function once the page is done loading.

      window.addEventListener('load', startup, false);
    // })();
  </script>
</head>
<body>
<h1>MDN - WebRTC: Simple RTCDataChannel sample</h1>
<p>This sample is an admittedly contrived example of how to use an <code>RTCDataChannel</code> to
  exchange data between two objects on the same page. See the
  <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Simple_RTCDataChannel_sample">
    corresponding article</a> for details on how it works.</p>

<div class="controlbox">
  <button id="connectButton" name="connectButton" class="buttonleft">
    Connect
  </button>
  <button id="disconnectButton" name="disconnectButton" class="buttonright" disabled>
    Disconnect
  </button>
</div>

<div class="messagebox">
  <label for="message">Enter a message:
    <input type="text" name="message" id="message" placeholder="Message text"
           inputmode="latin" size=60 maxlength=120 disabled>
  </label>
  <button id="sendButton" name="sendButton" class="buttonright" disabled>
    Send
  </button>
</div>
<div class="messagebox" id="receivebox">
  <p>Messages received:</p>
</div>
</body>
</html>
